#ifndef EVENT_MANAGER_H_
#define EVENT_MANAGER_H_

#include "base/base.h"

#define EV_READ 1 << 1
#define EV_WRITE 1 << 2
#define EV_ERROR 1 << 3

namespace rpc {
struct Event {
    int32 fd;
    short event;
    void *arg;
    void (*cb)(int fd, void* arg, int event);
};

class EventManager {
  public:
    virtual ~EventManager() {
      Stop();
    }

    virtual bool Init() = 0;
    virtual void Stop() {
      if (!exit_) {
        exit_ = true;
        loop_thread_.reset();
      }
    }

    void AssertInLoopThread() {
      CHECK_EQ(loop_tid_, ::pthread_self());
    }
    void RunInLoopThread(Closure* cb);

    virtual bool Add(Event* ev, int flag) = 0;
    virtual void Del(Event* ev, int flag) = 0;
    virtual bool Mod(Event* ev, int flag) = 0;

    // change exit_ false
    // update loop_tid_
    virtual void Loop() = 0;

    void LoopInAnothreadThread() {
      loop_thread_.reset(
          new StopableThread(NewPermanentCallback(this, &EventManager::Loop)));
      CHECK_NOTNULL(loop_thread_.get());
      loop_thread_->Start();
    }

  protected:
    bool exit_;

    EventManager();
    void HandleCb();

  private:
    pthread_t loop_tid_;
    scoped_ptr<StopableThread> loop_thread_;

    Mutex mutex_;
    std::deque<Closure*> tasks_;
    class EventFd;
    scoped_ptr<EventFd> cb_fd_;

    DISALLOW_COPY_AND_ASSIGN(EventManager);
};

EventManager* CreateEventManager();

}
#endif  // SRC_NET_EV_POLL_H
